Connectome is an R package to automate ligand-receptor mapping and visualization in single-cell data. It is built to work with Seurat from Satija Lab.

Load dependencies

require(Seurat)
require(SeuratData)
require(connectome)

Data Preparation

CreateConnectome uses the active identity slot in a Seurat 3.0 object to define “nodes” for network creation and network analysis.

Node parcellation should be done carefully as it will have a non-trivial effect on downstream connectomics.

Load Data

Here, we run Connectome on the cross-platform Pancreas data distributed by SeuratData:

InstallData('panc8')
data('panc8')
table(Idents(panc8))
#> 
#>     celseq    celseq2 fluidigmc1     indrop  smartseq2 
#>       1004       2285        638       8569       2394
Idents(panc8) <- panc8[['celltype']]
table(Idents(panc8))
#> 
#>              gamma             acinar              alpha 
#>                625               1864               4615 
#>              delta               beta             ductal 
#>               1013               3679               1954 
#>        endothelial activated_stellate            schwann 
#>                296                474                 25 
#>               mast         macrophage            epsilon 
#>                 56                 79                 30 
#> quiescent_stellate 
#>                180

Scale and make connectome

panc8 <- NormalizeData(panc8)
connectome.genes <- union(connectome::ncomms8866_human$Ligand.ApprovedSymbol,connectome::ncomms8866_human$Receptor.ApprovedSymbol)
genes <- connectome.genes[connectome.genes %in% rownames(panc8)]
panc8 <- ScaleData(panc8,features = genes)
panc8.con <- CreateConnectome(panc8,species = 'human',min.cells.per.ident = 75,p.values = F,calculate.DOR = F)
#> 
  |                                                                       
  |                                                                 |   0%
  |                                                                       
  |======                                                           |  10%
  |                                                                       
  |=============                                                    |  20%
  |                                                                       
  |====================                                             |  30%
  |                                                                       
  |==========================                                       |  40%
  |                                                                       
  |================================                                 |  50%
  |                                                                       
  |=======================================                          |  60%
  |                                                                       
  |==============================================                   |  70%
  |                                                                       
  |====================================================             |  80%
  |                                                                       
  |==========================================================       |  90%
  |                                                                       
  |=================================================================| 100%

Filter to edges of interest (critical step - data dependent)

panc8.con2 <- FilterConnectome(panc8.con,min.pct = 0.1,min.z = 0.25,remove.na = T)

Network plot

NetworkPlot(panc8.con2,features = 'VEGFA',min.pct = 0.75,weight.attribute = 'weight_sc')

ModalDotPlot (all modes)

ModalDotPlot(panc8.con2,modes.include = NULL,min.z = NULL,weight.attribute = 'weight_sc')

ModalDotPlot (limited modes)

ModalDotPlot(panc8.con2,modes.include = c('VEGF','WNT','Semaphorins','NOTCH','FGF'),weight.attribute = 'weight_sc',min.z = 0)

CellCellScatter

p1 <- CellCellScatter(panc8.con2,sources.include = 'endothelial',targets.include = 'activated_stellate',
                label.threshold = 3,
                weight.attribute = 'weight_sc',min.pct = 0.25,min.z = 2)
p1 <- p1 + xlim(0,NA) + ylim(0,NA)
p1

SignalScatter

p2 <- SignalScatter(panc8.con2, features = c('JAG1','JAG2','DLL4'),label.threshold = 1,weight.attribute = 'weight_sc',min.z = 2)
p2 <- p2 + xlim(2,NA) + ylim(2,NA)
p2

Four kinds of CircosPlots

First, let’s select the top 5 signaling vectors for each cell-cell vector

test <- panc8.con2
test <- data.frame(test %>% group_by(vector) %>% top_n(5,weight_sc))

Edgweights from normalized data slot

cells.of.interest <- c('endothelial','activated_stellate','quiescent_stellate','macrophage')
CircosPlot(test,weight.attribute = 'weight_norm',sources.include = cells.of.interest,targets.include = cells.of.interest,lab.cex = 0.6)

Edgweights from scaled data slot

CircosPlot(test,weight.attribute = 'weight_sc',sources.include = cells.of.interest,targets.include = cells.of.interest,lab.cex = 0.6)

Ligand-receptor tapered edges from normalized data slot

CircosPlot(test,weight.attribute = 'weight_norm',sources.include = cells.of.interest,targets.include = cells.of.interest,balanced.edges = F,lab.cex = 0.6)

Ligand-receptor tapered edges from scaled data slot

CircosPlot(test,weight.attribute = 'weight_sc',sources.include = cells.of.interest,targets.include = cells.of.interest,balanced.edges = F,lab.cex = 0.6)

Niche-wise investigation:

CircosPlot(test,targets.include = 'endothelial',lab.cex = 0.6)

Source-wise investigation:

CircosPlot(test,sources.include = 'endothelial',lab.cex = 0.6)